/** @author paim 29/03/2011 */
package paim.wingchun.controller;


import java.util.List;
import java.util.stream.Collectors;

import javax.swing.JComponent;

import paim.wingchun.controller.eventos.DefaultPanelButtonsEvent;
import paim.wingchun.model.modelos.ErroModel.Level;
import paim.wingchun.model.pojos.Erro;
import paim.wingchun.model.pojos.Pojo;
import paim.wingchun.view.AbstractListView;
import paim.wingchun.view.AbstractView;
import paim.wingchun.view.AbstractView.Estado;
import paim.wingchun.view.Dialogs;

/** lista de objetos de mesma classe
 *
 * @author paim 29/03/2011 */
public abstract class AbstractListController<P extends Pojo, V extends AbstractListView<P>> extends
                AbstractController<P, V> implements ControllerListener {

    protected AbstractListController() {
        super();
    }

    protected <V2 extends AbstractView<P>> AbstractListController(AbstractController<P, V2> parent) {
        super(parent);
    }

    protected <P2 extends Pojo, V2 extends AbstractView<P2>, C extends AbstractController<P2, V2> & HasConstrutor> AbstractListController(
                    C parent, P2 parentPojo, JComponent parentComponent, Class<P> pClass) {
        super(parent, parentPojo, parentComponent, pClass);
    }

    @Override
    protected boolean c_cancelar(Object objeto) throws Exception {
        if ( !List.class.isAssignableFrom(objeto.getClass()) )
            throw new Exception();

        List<Pojo> pojos = getPojosIniciais();
        List<Pojo> recarregados = getModelo().reLoad(getSessao(), pojos);
        setObjeto(recarregados);
        refreshErrosSlow(recarregados);
        getVisao().setEditando(false);
        return true;
    }

    @Override
    protected Estado c_confirmar(final Object objeto, List<Erro> erros) throws Exception {

        if ( !List.class.isAssignableFrom(objeto.getClass()) )
            throw new Exception();

        AbstractView.Estado retorno = AbstractView.Estado.Alterado;

        // List<Erro> impeditivos = (List<Erro>) Collections2.filter(erros, Funcoes.ERRO.impeditivos());
        /* usando java8 lambda */
        List<Erro> impeditivos = erros.stream()
                        .filter(e -> e.getLevel().getValor() >= Level.ERRO$IMPEDITIVO.getValor())
                        .collect(Collectors.toList());

        getVisao().refreshErros(erros);

        if ( !impeditivos.isEmpty() ) {
            if ( Dialogs.showConfirmErros(this.getVisao(), impeditivos) ) {
                cancelar();
                retorno = AbstractView.Estado.Descartado;
            }
        }
        else {
            getModelo().saveOrUpdate(getSessao(), objeto);
            /* refresh visao */
            setObjeto(objeto);
            refreshErrosSlow(objeto);
            getVisao().setEditando(false);
            retorno = AbstractView.Estado.Confirmado;
        }

        return retorno;
    }

    @Override
    protected boolean c_incluir(P novoPojo) throws Exception {
        /* busca a lista da visao */
        List<P> lista = (List<P>) getObjeto();
        /* adiciona novo pojo */
        lista.add(novoPojo);
        /* coloca na visao */
        setObjeto(lista);
        return false;
    }

    @Override
    protected Object cPopulaVisao() throws Exception {
        /* busca todos objetos do banco */
        List<Pojo> objetos = getPojosIniciais();
        /* prepara para jogar na visao */
        setObjeto(objetos);

        return objetos;
    }

    @Override
    void addListeners() throws Exception {
        /* listener de eventos do wc */
        this.addListener(this);
        /* botoes confirmas, cancelar, .... */
        getVisao().getjPanelBotoes().addListener(new DefaultPanelButtonsEvent(this));
    }

    protected List<Pojo> getPojosIniciais() throws Exception {
        List<Pojo> objetos = getModelo().list(getSessao());
        return objetos;
    }

    @Override
    protected void devolver(Object objeto) throws Exception {
        /* se ambos controladores tem mesma sessao */
        ((HasConstrutor) getPai()).recebeObjeto(objeto, getComponentPai());
    }

    protected boolean excluir(List<Pojo> lista, Pojo pojo) {
        // TODO exclusao de um objeto da lista
        return false;
    }

    // public abstract POJO selecionar();

    @Override
    public void eventOccurred(WC_Event e) {
        switch ( (Eventos) e.evento() ) {
            case ALTERANDO:
            default:
                // refreshErrosSlow(e.getObjeto());
                // ((POJO) e.getObjeto()).setAlterado(true);
                getVisao().setEditando(true);
            break;
        }
    }

}
